﻿using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace TCG
{
	public static class PrefabSerializer 
	{
		/// <summary>
		/// Serialize the specified prefab.
		/// </summary>

		public static void Serialize (GameObject prefab)
		{
			// 检查路径是否合法
			string targetPath = GameEditorTools.GetPathForSerilize (prefab);
			if (string.IsNullOrEmpty (targetPath))
			{
				throw new System.Exception (string.Format ("预设{0}应该位于{1}文件夹或其子文件夹中", prefab.name, GameEditorTools.SerializableSourceDir));
			}

			// 预设在打包时，要解除和材质的依赖关系，要不然会多个预设可能会包含重复的贴图、shader等。
			// 先临时创建一份拷贝，记录其中的所有材质，将材质列表记录起来，然后删除拷贝上的材质，再打包就可以
			PrefabData prefabData = new PrefabData ();
			prefabData.prefabId = CommonTools.ParseAssetIdFromName (prefab.name);
			prefabData.renderDatas = new List<PrefabRenderData> ();

			GameObject instance = GameObject.Instantiate (prefab) as GameObject;
			Renderer[] renders = instance.GetComponentsInChildren<Renderer> (true);
			foreach (Renderer _render in renders)
			{
				Material[] mats = _render.sharedMaterials;
				if (mats.Length == 0) continue;

				PrefabRenderData renderData = new PrefabRenderData ();
				renderData.transformPath = GetTransformPath (_render.transform);

				renderData.sharedMatIds = new List<uint> ();
				foreach (Material _mat in mats)
				{
					renderData.sharedMatIds.Add (CommonTools.ParseAssetIdFromName (_mat.name));
				}
				prefabData.renderDatas.Add (renderData);

				// 剔除材质
				_render.materials = new Material[0];
			}

			// 将prefabData写入文件中，以 _meta 结尾
			System.IO.Stream fileStream = new System.IO.FileStream (targetPath + "_meta", System.IO.FileMode.Create);
			prefabData.Serialize (fileStream);
			fileStream.Close ();


			// 将剔除材质后的实例保存为prefab，然后打包，最后删除
			string rawPrefabPath = AssetDatabase.GetAssetPath (prefab);
			int suffixIndex = rawPrefabPath.LastIndexOf (".prefab");
			string clonedPrefabPath = rawPrefabPath.Insert (suffixIndex, "_clone");
			GameObject clonedPrefab = PrefabUtility.CreatePrefab (clonedPrefabPath, instance, ReplacePrefabOptions.ConnectToPrefab);
			AssetDatabase.Refresh ();
			BuildPipeline.BuildAssetBundle (clonedPrefab, null, targetPath, BuildAssetBundleOptions.CollectDependencies, GameEditorTools.GetBuildTarget ());

			AssetDatabase.DeleteAsset (clonedPrefabPath);
			GameObject.DestroyImmediate (instance);
			
			AssetDatabase.Refresh ();
		}
		
		
		static string GetTransformPath (Transform trans)
		{
			StringBuilder sb = new StringBuilder ();

			while (trans != null)
			{
				if (trans.parent == null)
				{
					break;
				}

				sb.Insert (0, trans.name + "/");

				trans = trans.parent;
			}

			if (sb.Length > 0)
			{
				sb.Remove (sb.Length - 1, 1);
			}

			return sb.ToString ();
		}
	}
}